﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Anonym.Data.Entities;
using Anonym.Data;
using SqlSugar;
using Microsoft.Extensions.DependencyInjection;
using Anonym.Common;
using Anonym.Common.MyAttribute;
using Microsoft.AspNetCore.Mvc.Controllers;
using Anonym.Models.Common;
using Anonym.Models.Objects;
using Anonym.Service;
using Newtonsoft.Json;

namespace Anonym.MVC.Filter
{
    public class FirstFilter : IActionFilter
    {
        private SqlSugarClient Db { get; set; }
        private Log_Interface Li { get; set; }
        private IServiceProvider ServiceProvider { get; set; }
        private CmsBasicsInfo CmsBasicsInfo { get; set; }

        public FirstFilter(IServiceProvider p)
        {
            #region 通过IHttpContextAccessor传值
            //, IHttpContextAccessor a
            //a.HttpContext.Items.Add("bbb", new { dingjun = 111, name = 222 });
            #endregion

            ServiceProvider = p;
            Db = ServiceProvider.GetService<DbProvider>().GetInstance();
            Li = new Log_Interface();
            CmsBasicsInfo = ServiceProvider.GetService<CmsBasicsInfo>();
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            #region 测试数据
            //User u = ServiceProvider.GetService<User>();
            //u.Test = "rinima";
            CmsBasicsInfo.ID = 888;
            CmsBasicsInfo.Name = "DingJun";
            CmsBasicsInfo.CompanyId = 1;
            //_p.GetService<IServiceCollection>().AddScoped<Log_Interface>(); //这里注册了，但是其他地方注入不起
            #endregion

            HttpRequest request = context.HttpContext.Request;
            bool isBodySubmit = !request.HasFormContentType;    //是否是通过body提交的参数
            var ps = context.ActionDescriptor.Parameters;   //取action的参数列表
            string bodyVal = "";

            #region request取值

            if (isBodySubmit)
            {
                //context.HttpContext.Request.EnableBuffering();

                Stream stream = context.HttpContext.Request.Body;
                var requestReader = new StreamReader(stream);
                context.HttpContext.Request.Body.Position = 0;
                bodyVal = requestReader.ReadToEndAsync().Result;
                context.HttpContext.Request.Body.Position = 0;
                //CmsBasicsInfo.DicRequest = bodyVal.ToObject<Dictionary<string, string>>();
                Dictionary<string, string> requestTempDic = bodyVal.ToObject<Dictionary<string, string>>();
                if (requestTempDic != null)
                    foreach (var i in requestTempDic)
                    {
                        //转小写
                        CmsBasicsInfo.DicRequest.Add(i.Key.ToLower(), i.Value);
                    }
            }
            else
            {
                //Dictionary<string, string> dic = new Dictionary<string, string>();
                if (request.Method == "POST")
                {
                    foreach (var i in request.Form)
                    {
                        CmsBasicsInfo.DicRequest.Add(i.Key.ToLower(), i.Value);
                    }
                }
                else
                {
                    foreach (var i in request.Query)
                    {
                        CmsBasicsInfo.DicRequest.Add(i.Key.ToLower(), i.Value);
                    }
                }
                bodyVal = JsonConvert.SerializeObject(CmsBasicsInfo.DicRequest);
            }

            #endregion

            #region 通用request参数赋值
            if (ps.Count > 0 && ps[0].ParameterType.Name == "CommonRequest")
            {
                foreach (var item in ps[0].ParameterType.GetProperties())
                {
                    if (item.Name == "RequestContent" && item.PropertyType.Name == "String")
                        item.SetValue(context.ActionArguments[ps[0].Name], bodyVal);
                }
            }
            #endregion

            #region 记录日志

            //写日志信息
            Li.Link = request.GetEncodedUrl();
            Li.ControlName = context.RouteData.Values["controller"] + "";
            Li.ActionName = context.RouteData.Values["action"] + "";
            Li.StartTime = DateTime.Now;
            Li.Source = "pc";
            Li.Ver = "1.0";
            //Li.UserId = 0;
            //Li.ClientTime { get; set; } = new DateTime(1900, 1, 1);
            Li.Par = bodyVal;
            //Li.RequestIp = context.HttpContext.GetClientIp();
            Li.RequestIp = context.HttpContext.Connection.RemoteIpAddress.ToString();
            Li.Method = request.Method;

            #endregion

            #region 3种向action传递值的方式。注意：在控制器的构造方法中取不到，action中才能取到。
            //context.ActionArguments["loginInfo"] = Li;
            //context.RouteData.Values.Add("aaa", Li);
            //context.HttpContext.Items.Add("bbb", Li);
            #endregion

            bool isNoToken = false;   //是否不需要登录，默认需要
            bool isCmsNoMenuPage = false;
            //判断Action是否跳过验证
            //if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
            //{
            //    if (controllerActionDescriptor.MethodInfo.GetCustomAttributes(
            //           .Any(a => a.GetType().Equals(typeof(SkipActionFilterAttribute))))
            //        {
            //        ischeck = true;
            //    }
            //}

            var action = context.ActionDescriptor as ControllerActionDescriptor;
            isNoToken = action.MethodInfo.GetCustomAttributes(true).Any(w => w.GetType().Name == typeof(NoTokenAttribute).Name);   //判断不需要登录标签
            isCmsNoMenuPage = action.MethodInfo.GetCustomAttributes(true).Any(w => w.GetType().Name == typeof(CmsNoMenuPageAttribute).Name);

            #region 用户验证
            //if (!isNoToken) //需要登录
            if (false)
            {
                if (string.IsNullOrEmpty(context.HttpContext.Session.GetString("user")))
                {
                    Error error = new Error()
                    {
                        Msg = "您还未登录系统，或长时间未操作系统，请重新登录！",
                        Code = 8001,
                        Url1 = "/home/login",
                        UrlStr = "返回登录页面",
                        Target = "_top",
                    };
                    context.HttpContext.Session.SetObject("Error", error);
                    //HttpContext.Response.Redirect("/login/index");
                    context.Result = new RedirectResult("/Home/Error/");
                    return;
                }
                //CmsBasicsInfo user = HttpContext.Session["user"] as CmsBasicsInfo;
                CmsBasicsInfo = context.HttpContext.Session.GetObject<CmsBasicsInfo>("user");
                CmsBasicsInfo.Ip = Li.RequestIp;

                //检查用户
                if (Db.Queryable<Cms_User>().Where(w => w.State == 0 && w.Name == CmsBasicsInfo.Name && w.Password == CmsBasicsInfo.Password).Count() <= 0)
                {
                    context.HttpContext.Session.SetString("user", null);
                    Error error = new Error()
                    {
                        Msg = "您还未登录系统，或长时间未操作系统，请重新登录！",
                        Code = 8001,
                        Url1 = "/home/login",
                        UrlStr = "返回登录页面",
                        Target = "_top",
                    };
                    context.HttpContext.Session.SetObject("Error", error);
                    context.Result = new RedirectResult("/Home/Error/");
                    return;
                }
            }
            else //不需要登录
            {

            }
            #endregion

            #region 公司验证
            if (Db.Queryable<Cms_Company>().Where(w => w.ID == CmsBasicsInfo.CompanyId && w.State == 0).Count() <= 0)
            {
                Error error = new Error()
                {
                    Msg = "公司使用权限被禁用，请联系管理员！",
                    Code = 8004,
                    Url1 = "/home/login",
                    UrlStr = "返回登录页面",
                    Target = "_top",
                };
                context.HttpContext.Session.SetObject("Error", error);
                context.Result = new RedirectResult("/Home/Error/");
                return;
            }
            #endregion

            //没有菜单的页面
            if (isCmsNoMenuPage)
                return;

            #region 菜单验证
            string controlName = Li.ControlName;
            string actionName = Li.ActionName;
            try
            {
                //var arr = url.Split('/');
                //controlName = arr[1];
                //actionName = arr[2].IndexOf('?') < 0
                //    ? arr[2]
                //    : arr[2].Substring(0, arr[2].IndexOf('?'));
            }
            catch (Exception ex)
            {
                Error error = new Error()
                {
                    Msg = "地址异常，请返回重试！",
                    Code = 8003,
                    Url1 = "/home/login",
                    UrlStr = "返回登录页面",
                    Target = "_top",
                };
                context.HttpContext.Session.SetObject("Error", error);
                context.Result = new RedirectResult("/Home/Error/");
                return;
            }
            if (string.IsNullOrEmpty(controlName) || string.IsNullOrEmpty(actionName))
            {
                Error error = new Error()
                {
                    Msg = "地址异常，请返回重试！",
                    Code = 8003,
                    Url1 = "/home/login",
                    UrlStr = "返回登录页面",
                    Target = "_top",
                };
                context.HttpContext.Session.SetObject("Error", error);
                context.Result = new RedirectResult("/Home/Error/");
                return;
            }

            string sql = "";
            if (CmsBasicsInfo.IsSuper != 1) //普通用户
            {
                sql = @"
select count(0) from cms_user a 
	left join Cms_UserGroupMap b on a.id = b.userid
	left join Cms_MenuPermissions c on b.groupid = c.groupid
	left join Cms_Menu d on d.id = c.MenuId
	left join Cms_MenuMap e on d.id = e.MenuId
	left join Cms_UserGroup f on b.groupid = f.id
where a.id = @uid and d.CompanyId = @CompanyId and e.controlname = @controlname and e.actionname = @actionname and f.State = 0";

                Dictionary<string, object> mapDic = new Dictionary<string, object>();
                //mapDic.Add("@uid", CmsBasicsInfo.ID); //这样写报错，麻痹的
                mapDic.Add("uid", CmsBasicsInfo.ID);
                mapDic.Add("CompanyId", CmsBasicsInfo.CompanyId);
                mapDic.Add("controlname", controlName + "Controller");
                mapDic.Add("actionname", actionName);
                //if (int.Parse(Db.Ado.GetScalar(sql, mapDic) + "") <= 0)
                if(false)
                {
                    Error error = new Error()
                    {
                        Msg = "您没有权限，请返回重试！",
                        Code = 8002,
                        Url1 = "/home/login",
                        UrlStr = "返回登录页面",
                        Target = "_top",
                    };
                    context.HttpContext.Session.SetObject("Error", error);
                    context.Result = new RedirectResult("/Home/Error/");
                    return;
                }
            }
            #endregion

            return;
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            Li.EndTime = DateTime.Now;
            //Li.WastageTime = (Li.EndTime - Li.StartTime).Seconds;
            Li.WastageTime = Convert.ToDecimal(Li.EndTime.Subtract(Li.StartTime).TotalSeconds);

            if (context.Result is ObjectResult)
            {
                //var ss = context.Result;
                //var objectResult = context.Result as ObjectResult;
                //var cc = objectResult.Value;
                //objectResult.Value = "333333333333333333";
                //ss = objectResult;
                ObjectResult obj = context.Result as ObjectResult;
                //string repVal = obj.Value;
                Li.ReturnValue = obj.Value + "";
            }

            Db.Insertable(Li).ExecuteCommand();
        }
    }
}